home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-06-25 | 9.9 KB | 225 lines | [TEXT/R*ch] |
- The following is an extract from a reply I wrote to a Mac programming forum during
- the development of Fantasm V2. Whilst V3 has global include files for traps and system
- variables, the chat below still explains nicely what a Mac trap is, and how you can find out
- which trap you need. The header files mentioned below are included on Fantasm V3.xx
- disk #4.
- ------------------------------------------------------------------------------------
-
- Traps - right, on a 68k you have 16 hardware traps - 0 to 15.
- On a Mac, operating system calls are also called TRAPS, just to confuse
- machine code programmers!!!!
-
- So, any call to the OS, in Mac parlance is a trap.
- Traps work by defining a special 68K illegal instruction. All 68K instruction
- op codes are 16 bits - for example $4e75 is the 68K instruction for RTS.
-
- So, in assembler, you could either write RTS or dc.w $4e75 - its the same thing.
- Of course RTS is much easier to remember than $4e75, thats why we have assemblers!
-
- Any instruction along the lines of $Axxx causes the 68k to jump through the
- "line a vector" to a software routine that implements this instruction. If you
- like its a way of synthesising instructions, or extending the processors instruction
- set through software.
- The routine at the line a vector examines the instruction, then jumps to
- the right routine to handle it.
- So for example if we dc.w $a982 (close dialog), when the 68K jumps to the line a vector,
- the code there examines the instruction, says "Oh yeah, close dialog" and jumps to
- the software that closes a dialog box.
-
- Of course, some "traps" need parameters - these are normally passed on the stack.
- Consider:
- closedialog: equ $a982 *define close dialog trap
- ..... *open dialog
- ...... *and processing
- .....
- **now close the dialog box
- move.l dialog_handle(pc),-(sp) *pass the dialogs handle
- dc.w closedialog *close dialog "trap"
- rts
-
- (BTW, the amount of typing involved in the above code is far less than the equivalent
- C code, and without remembering the semicolons, brackets, squigily brackets and
- other C nause!)
- Sometimes however, the parameters are passed in 68K registers, although these
- are few on the ground, and sometimes, as in the shutdown example, in data regs and
- on the stack - what I call a voodoo trap, perform some magical incantations over
- the keyboard until it works,basically!, but I'm sure apple have a more scientific
- explanation - (or maybe not) :-)
-
- To define a trap, you need to insert the trap word into the code. We do this with
- the DC directive. As all traps definitions are words, we use DC.W. Its also far more
- readable to equate the trap numbers to their real names, rather than just using the
- numbers (as I did in the quick and dirty shutdown example! But its ok,
- I'm a professional?!?!)
-
- Anyway, as some registered users of fantasm have pointed out, where do you find
- out these (sometimes obscure) trap calls, they werent included in the package!
-
- Well they are available as the C header files for the MPW (Macintosh Programmers Workshop
- - *NOT* Macintosh Programmers Workbench as stated in a rather popular Mac magazine this
- month) developers system. They may still be available on Apple Crackers. If anybody
- has problems obtaining these files, they may magically appear on Portland and Cosmos,
- although dont ask me how :-)
-
- What you get is 780K of header files for all current mac OS traps, sometimes called
- Toolbox traps. As a simple example, of first a trap that uses registers,
- lets assume we want to get 30k of memory from the system, to use as a buffer.
- We look up the header files, and in the MEMORY file we find:
-
- #pragma parameter __A0 NewPtr(__D0)
- pascal Ptr NewPtr(Size byteCount)
- = 0xA11E;
-
- This tells use the trap name is NewPtr. We think, yes, we want a new pointer to a buffer,
- so that'll probably do. Next we need know what parameters we need.
- Well, we see "pascal Ptr NewPtr(Size bytecount)". This is how to call the trap from
- pascal. From this we can determine that the trap needs a parameter called byteCount
- and it returns a pointer.
- Now to translate that into machine code, the line:
-
- #pragma parameter __A0 NewPtr(__D0)
-
- Tells use that the input paramter goes in d0, and the trap returns the new pointer
- in a0.
- Finally, the bottom line, = 0xA11E, gives use the actual trap number.
-
- To summarise, the number of bytes we want goes in d0, the trap returns the address
- of the start of the block (the pointer) in A0 and the trap number is $a11e.
- So:
- newptr: equ $a11e
-
- getmybuffer: move.l #30*1024,d0 the input parameter is 30kbytes
- dc.w newptr do newptr trap
- move.l a0,mybufferaddress(a6)
- rts
- mybufferaddress now contains the start address of a 30K block of memory you can use.
-
- NOTE, if a trap cant be completed, and error will be returned, in this case in d0
- with a0 being zero.
- The errors are normally negative numbers, and are listed in the header files as
- "errors.h". So a more realistic routine would be:
-
- newptr: equ $a11e *equates normally live in an include file!
-
- getmybuffer: move.l #30*1024,d0 *we want 30K
- dc.w newptr *get it from allocated memory
- tst.l a0 *check for error
- beq error *system couldnt allocate memory!
- move.l a0,mybufferaddress(a6) *save pointer
- rts
-
- **SNIPPET - nearly all memory traps use registers, normally d0 for the input parameter
- and a0 for the return parameter**
-
- **BIG TIP - Mac memory management is nothing to write home about, using newptr to
- define every block of memory you need is very slow. The best way is too grab all
- free memory, with the MAXMEM trap, then use your own routines to allocate memory
- from that big block - registered users of fantasm will be given the details on request**
-
- Ok, now a stack based trap, hang on, just make a cup of coffee....Ahh Nescafé...
- (Sorry, but I've always wanted to use one of those e things)
-
- Normally, the mac OR's characters onto the screen when you are printing, this
- is fine, until you want to overwrite some text in a window.
- For example, suppose we have a counter on the screen in the bottom right. The counter
- starts a 0, then 1 and so on. First the 0 is printed, next the 1, but because
- the Mac is oring the characters on the screen, the 1 is mixed in with the 0!
- One way to get round this is delete the 0 first - somehow, the other way is to
- set the Mac to overwrite characters, instead of oring them.
-
- In the quickdraw headers file, there is a trap to set the screen writing mode -
-
- pascal void TextMode(short mode)
- = 0xA889;
- We can see, the parameter is defined a "short mode", well short means word, and as
- there are no registers defined, it must go on the stack. Mode can be numerous values,
- but the two we're interested in here is 1=OR drawing mode, and 0=replace drawing mode.
- The word "void" means the trap returns nothing.
- So:
- TEXT_MODE: EQU $A889
-
- MOVE.W #1,-(A7) ; *OR DRAWING MODE
- DC.W TEXT_MODE
-
- MOVE.W #0,-(A7)
- DC.W TEXT_MODE ; *REPLACE DRAWING MODE
-
- Now lets look at a trap that returns a parameter on the stack:
-
- pascal short OpenResFile(ConstStr255Param fileName)
- = 0xA997;
-
- pascal void UseResFile(short refNum)
- = 0xA998;
-
- Openresfile returns a refnum to the resource fork of a file. Suppose you wanted
- your application to read one of its resources into memory. First thing you have to do is
- tell the mac which resource file to use, so by reference to the above two trap
- definitions:
-
- openresfile: equ $a997
- useresfile: equ $a998
-
- open_my_res: pea my_filename *push our filename onto the stack
- dc.w openresfile *open our resource fork
- move.w (sp)+,res_refnum *save our refnum
-
- move.w res_refnum,-(sp)
- dc.w useresfile
- rts
- my_filename: dc.b 9,"stus_file" *our filename in pascal format
- even
- res_refnum: ds.w 1 *space for refnum
-
- Firstly, note this code segment is written in position dependant code, for
- simplicity. Secondly, notice that the filename is given in Pascal format.
- Users of Fantasm V3.xx can use the C_TO_P library functione to convert a C string
- "Stus_file",0 to a pascal string.
- Thirdly, notice the way the return parameter from openresfile is "POPPED"
- off the stack, using the post increment addressing mode, thus getting the return
- parameter *and* tidying up the stack.
-
-
- Ok, so considering the above, lets look at the shutdown code:
-
- pascal void ShutDwnPower(void)
- = {0x3F3C,0x0001,0xA895};
-
- This unfortunately, gives us no clues whatsoever! If somebody can explain how a compiler
- can translate this, then please let me know!
-
- I translated it by stepping through the shutdown trap in Macsbug, to find out what it
- expected, and this is what I came up with, maybe somebody with Inside Mac can explain?
- Anyway, this is my interpretation:
-
- pascal void ShutDwnPower(void)
- = {0x3F3C, 0x0001, 0xA895};
- Shutdown | | |
- 1=shutdown, 2=restart | |
- The trap number |
-
- shutdown: Move.w #1,-(sp) 1=shutdown, 2=restart
- move.l #$3f3c,d0 Shutdown, as A895 is used for other shutdown procedures.
- dc.w $a895 trap number.
- rts
-
- As you can see from this one, sometimes a trap number is used for more than one specific
- function, so additional qualifiers are needed - the 3f3c for example.
-
- Hope this explains how to translate header files a little Dave.
- You are quite right about the diskeject trap, needing a parameter block. The PB
- in question is as detailed in the Fantasm beginners guide - i.e .the Mac has to know
- which disk specifically to eject, so the PB is important, as the Mac could be on
- a network! :-)
- BTW, you wont harm your HD by ejecting it accidentally whilst experimenting (been
- there, done that etc), but I never said that, if you (or anybody else) trashes their
- HD!
-
- ------------------------------------------------------------------------------------
- For Fantasm V3.xx, there is no need to equate the trap numbers. They've all been
- done for you in the file Mac_traps.s in the standard includes folder on disk 1
- (registered versions only!) All
- you ned do is copy these include files into your project global includes file, then you
- can use the trap names without equating them first. Note that all the trap names
- are preceded by the underscore character.
-